<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="theme-color" content="#0078E7"><meta name="author" content="爱肖彤真是太好了"><meta name="copyright" content="爱肖彤真是太好了"><meta name="generator" content="Hexo 5.1.1"><meta name="theme" content="hexo-theme-yun"><title>Redis | 工藤旧二の博客</title><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@900&amp;display=swap" media="none" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/star-markdown-css@0.1.19/dist/yun/yun-markdown.min.css"><script src="//at.alicdn.com/t/font_1140697_stqaphw3j4.js" async></script><script src="https://cdn.jsdelivr.net/npm/scrollreveal/dist/scrollreveal.min.js" defer></script><script>document.addEventListener("DOMContentLoaded", () => {
  [".post-card",".post-content img"].forEach((target)=> {
    ScrollReveal().reveal(target);
  })
});
</script><link rel="shortcut icon" type="image/svg+xml" href="/task/yun.ico"><link rel="mask-icon" href="/task/yun.ico" color="#0078E7"><link rel="alternate icon" href="/yun.ico"><link rel="preload" href="/task/css/hexo-theme-yun.css" as="style"><link rel="preload" href="/task/js/utils.js" as="script"><link rel="preload" href="/task/js/hexo-theme-yun.js" as="script"><link rel="prefetch" href="/task/js/sidebar.js" as="script"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><link rel="stylesheet" href="/task/css/hexo-theme-yun.css"><link rel="alternate" href="/task/atom.xml" title="工藤旧二の博客" type="application/atom+xml"><script id="yun-config">
    const Yun = window.Yun || {};
    window.CONFIG = {"root":"/task/","title":"工藤旧二の博客","version":"0.9.7","anonymous_image":"https://cdn.jsdelivr.net/gh/YunYouJun/cdn/img/avatar/none.jpg","say":{"api":"https://v1.hitokoto.cn","hitokoto":true},"local_search":{"path":"/task/search.xml"},"fireworks":{"colors":["102, 167, 221","62, 131, 225","33, 78, 194"]}};
  </script><script>(function(){
  var bp = document.createElement('script');
  var curProtocol = window.location.protocol.split(':')[0];
  if (curProtocol === 'https') {
    bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
  }
  else {
    bp.src = 'http://push.zhanzhang.baidu.com/push.js';
  }
  var s = document.getElementsByTagName("script")[0];
  s.parentNode.insertBefore(bp, s);
})();</script><meta name="description" content="Redis[TOC] 一、redis简介介绍： redis是一个key-value存储系统。和Memcached类似，它支持存储的value类型相对更多，包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash（哈希类型）。这些数据类型都支持push&#x2F;pop、add&#x2F;remove及取交集并集和差集及更丰富的操作，而且这些操作都是原子性的。">
<meta property="og:type" content="article">
<meta property="og:title" content="Redis">
<meta property="og:url" content="http://huang_zhao.gitee.io/task/2021/06/27/%E6%95%B0%E6%8D%AE%E5%BA%93/redis/Redis/index.html">
<meta property="og:site_name" content="工藤旧二の博客">
<meta property="og:description" content="Redis[TOC] 一、redis简介介绍： redis是一个key-value存储系统。和Memcached类似，它支持存储的value类型相对更多，包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash（哈希类型）。这些数据类型都支持push&#x2F;pop、add&#x2F;remove及取交集并集和差集及更丰富的操作，而且这些操作都是原子性的。">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-06-27T06:10:11.000Z">
<meta property="article:modified_time" content="2021-06-27T09:18:22.000Z">
<meta property="article:author" content="爱肖彤真是太好了">
<meta property="article:tag" content="数据库">
<meta property="article:tag" content="redis">
<meta name="twitter:card" content="summary"><script src="/task/js/ui/mode.js"></script><link rel="stylesheet" href="/task/css/prism.css" type="text/css"></head><body><script defer src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script defer src="/task/js/ui/fireworks.js"></script><canvas class="fireworks"></canvas><div class="container"><a class="sidebar-toggle hty-icon-button" id="menu-btn"><div class="hamburger hamburger--spin" type="button"><span class="hamburger-box"><span class="hamburger-inner"></span></span></div></a><div class="sidebar-toggle sidebar-overlay"></div><aside class="sidebar"><script src="/task/js/sidebar.js"></script><ul class="sidebar-nav"><li class="sidebar-nav-item sidebar-nav-toc hty-icon-button sidebar-nav-active" data-target="post-toc-wrap" title="文章目录"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-list-ordered"></use></svg></li><li class="sidebar-nav-item sidebar-nav-overview hty-icon-button" data-target="site-overview-wrap" title="站点概览"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-passport-line"></use></svg></li></ul><div class="sidebar-panel" id="site-overview-wrap"><div class="site-info fix-top"><a class="site-author-avatar" href="/task/about/" title="爱肖彤真是太好了"><img width="96" loading="lazy" src="/task/Yun.png" alt="爱肖彤真是太好了"></a><div class="site-author-name"><a href="/task/about/">爱肖彤真是太好了</a></div><a class="site-name" href="/task/about/site.html">工藤旧二の博客</a><sub class="site-subtitle"></sub><div class="site-desciption"></div></div><nav class="site-state"><a class="site-state-item hty-icon-button icon-home" href="/task/" title="首页"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-home-4-line"></use></svg></span></a><div class="site-state-item"><a href="/task/archives/" title="归档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-archive-line"></use></svg></span><span class="site-state-item-count">57</span></a></div><div class="site-state-item"><a href="/task/categories/" title="分类"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-2-line"></use></svg></span><span class="site-state-item-count">2</span></a></div><div class="site-state-item"><a href="/task/tags/" title="标签"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="site-state-item-count">50</span></a></div><a class="site-state-item hty-icon-button" target="_blank" rel="noopener" href="https://yun.yunyoujun.cn" title="文档"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-settings-line"></use></svg></span></a></nav><hr style="margin-bottom:0.5rem"><div class="links-of-author"><a class="links-of-author-item hty-icon-button" rel="noopener" title="RSS" target="_blank" style="color:orange"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-rss-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="QQ" target="_blank" style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="GitHub" target="_blank" style="color:#6e5494"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-github-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="微博" target="_blank" style="color:#E6162D"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-weibo-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="豆瓣" target="_blank" style="color:#007722"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-douban-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://music.163.com/#/user/home?id=552858287" title="网易云音乐" target="_blank" style="color:#C20C0C"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-netease-cloud-music-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="知乎" target="_blank" style="color:#0084FF"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-zhihu-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" href="https://space.bilibili.com/15081363" title="哔哩哔哩" target="_blank" style="color:#FF8EB3"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-bilibili-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Twitter" target="_blank" style="color:#1da1f2"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-twitter-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Telegram Channel" target="_blank" style="color:#0088CC"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-telegram-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="E-Mail" target="_blank" style="color:#8E71C1"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-mail-line"></use></svg></a><a class="links-of-author-item hty-icon-button" rel="noopener" title="Travelling" target="_blank" style="color:var(--hty-text-color)"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-send-plane-2-line"></use></svg></a></div><hr style="margin:0.5rem 1rem"><div class="links"><a class="links-item hty-icon-button" href="/task/links/" title="我的小伙伴们" style="color:dodgerblue"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-genderless-line"></use></svg></a></div><br><a class="links-item hty-icon-button" id="toggle-mode-btn" href="javascript:;" title="Mode" style="color: #f1cb64"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-contrast-2-line"></use></svg></a></div><div class="sidebar-panel sidebar-panel-active" id="post-toc-wrap"><div class="post-toc"><div class="post-toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Redis"><span class="toc-text">Redis</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81redis%E7%AE%80%E4%BB%8B"><span class="toc-text">一、redis简介</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-%E4%BD%BF%E7%94%A8redis%E7%9A%84%E5%A5%BD%E5%A4%84"><span class="toc-text">1 使用redis的好处</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-redis%E7%9B%B8%E6%AF%94%E4%BA%8Ememcached%E7%9A%84%E4%BC%98%E5%8A%BF"><span class="toc-text">2 redis相比于memcached的优势</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-redis%E5%B8%B8%E8%A7%81%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98%E5%92%8C%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88"><span class="toc-text">3 redis常见的性能问题和解决方案</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#4-MySQL%E9%87%8C%E6%9C%892000w%E6%95%B0%E6%8D%AE%EF%BC%8Credis%E4%B8%AD%E5%8F%AA%E5%AD%9820w%E7%9A%84%E6%95%B0%E6%8D%AE%EF%BC%8C%E5%A6%82%E4%BD%95%E4%BF%9D%E8%AF%81redis%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E9%83%BD%E6%98%AF%E7%83%AD%E7%82%B9%E6%95%B0%E6%8D%AE"><span class="toc-text">4 MySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#5-redis-%E6%9C%80%E9%80%82%E5%90%88%E7%9A%84%E5%9C%BA%E6%99%AF"><span class="toc-text">5 redis 最适合的场景</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8"><span class="toc-text">二、基本使用</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-python%E6%93%8D%E4%BD%9Credis%E4%B9%8B%E6%99%AE%E9%80%9A%E9%93%BE%E6%8E%A5"><span class="toc-text">1 python操作redis之普通链接</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-python%E6%93%8D%E4%BD%9Credis%E4%B9%8B%E8%BF%9E%E6%8E%A5%E6%B1%A0"><span class="toc-text">2 python操作redis之连接池</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81redis%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%93%8D%E4%BD%9C"><span class="toc-text">三、redis字符串操作</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9B%9B%E3%80%81redis%E5%93%88%E5%B8%8C%E7%B1%BB%E5%9E%8B%E6%93%8D%E4%BD%9C"><span class="toc-text">四、redis哈希类型操作</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%94%E3%80%81redis%E9%93%BE%E8%A1%A8%E7%B1%BB%E5%9E%8B%E6%93%8D%E4%BD%9C"><span class="toc-text">五、redis链表类型操作</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%AD%E3%80%81%E5%85%B6%E4%BB%96%E6%93%8D%E4%BD%9C"><span class="toc-text">六、其他操作</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%83%E3%80%81%E7%AE%A1%E9%81%93"><span class="toc-text">七、管道</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%85%AB%E3%80%81django%E4%B8%AD%E4%BD%BF%E7%94%A8redis"><span class="toc-text">八、django中使用redis</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B9%9D%E3%80%81%E6%8E%A5%E5%8F%A3%E7%BC%93%E5%AD%98"><span class="toc-text">九、接口缓存</span></a></li></ol></li></ol></div></div></div></aside><main class="sidebar-translate" id="content"><div id="post"><article class="post-block" itemscope itemtype="https://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://huang_zhao.gitee.io/task/task/2021/06/27/%E6%95%B0%E6%8D%AE%E5%BA%93/redis/Redis/"><span hidden itemprop="author" itemscope itemtype="https://schema.org/Person"><meta itemprop="name" content="爱肖彤真是太好了"><meta itemprop="description"></span><span hidden itemprop="publisher" itemscope itemtype="https://schema.org/Organization"><meta itemprop="name" content="工藤旧二の博客"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">Redis</h1><div class="post-meta"><div class="post-time" style="display:block"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-calendar-line"></use></svg></span> <time title="创建时间：2021-06-27 14:10:11" itemprop="dateCreated datePublished" datetime="2021-06-27T14:10:11+08:00">2021-06-27</time></div><span class="post-count"><span class="post-symbolcount"><span class="post-meta-item-icon" title="本文字数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-file-word-line"></use></svg></span> <span title="本文字数">5.6k</span><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读时长"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-timer-line"></use></svg></span> <span title="阅读时长">22m</span></span></span><span class="post-busuanzi"><span class="post-meta-divider">-</span><span class="post-meta-item-icon" title="阅读次数"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg> <span id="busuanzi_value_page_pv"></span></span></span><div class="post-classify"><span class="post-category"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-folder-line"></use></svg></span> <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a class="category" href="/task/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/" style="--text-color:var(--hty-text-color)" itemprop="url" rel="index"><span itemprop="text">技术分享</span></a></span></span><span class="post-tag"><span class="post-meta-divider">-</span><a class="tag" href="/task/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">数据库</span></a><a class="tag" href="/task/tags/redis/" style="--text-color:var(--hty-text-color)"><span class="post-meta-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-price-tag-3-line"></use></svg></span><span class="tag-name">redis</span></a></span></div></div></header><section class="post-body" itemprop="articleBody"><div class="post-content markdown-body" style="--smc-primary:#0078E7;"><h1 id="Redis"><a href="#Redis" class="headerlink" title="Redis"></a>Redis</h1><p>[TOC]</p>
<h2 id="一、redis简介"><a href="#一、redis简介" class="headerlink" title="一、redis简介"></a>一、redis简介</h2><p>介绍：</p>
<p>redis是一个<strong>key-value</strong>存储系统。和Memcached类似，它支持存储的value类型相对更多，包括<strong>string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash（哈希类型）</strong>。这些数据类型都支持<strong>push/pop、add/remove</strong>及取交集并集和差集及更丰富的操作，而且这些操作都是原子性的。在此基础上，redis支持各种不同方式的排序。与memcached一样，为了保证效率，数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件，并且在此基础上实现了master-slave(主从)<strong>同步</strong></p>
<p>Q：为什么redis这么快</p>
<p>A：用了io多路复用减少了io操作对资源的消耗，在内存中使用，单线程单进程，避免了线程之前数据交互的资源消耗</p>
<h3 id="1-使用redis的好处"><a href="#1-使用redis的好处" class="headerlink" title="1 使用redis的好处"></a>1 使用redis的好处</h3><pre class=" language-python"><code class="language-python"><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> 速度快，因为数据存在内存中，类似于HashMap，HashMap的优势就是查找和操作的时间复杂度都是O<span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># 比mysql这种关系型数据库速度更快，原因是查找方式和存储方式</span>

<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> 支持丰富数据类型，支持string，list，set，sorted set，hash

<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> 支持事务，操作都是原子性，所谓的原子性就是对数据的更改要么全部执行，要么全部不执行
<span class="token comment" spellcheck="true"># 事务性支持也没那么好，如果需要事务严格遵守的流程，比如转账功能，必定用的还是mysql等</span>

<span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span> 丰富的特性：可用于缓存，消息，按key设置过期时间，过期后将会自动删除</code></pre>
<h3 id="2-redis相比于memcached的优势"><a href="#2-redis相比于memcached的优势" class="headerlink" title="2 redis相比于memcached的优势"></a>2 redis相比于memcached的优势</h3><pre class=" language-python"><code class="language-python"><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> memcached所有的值均是简单的字符串，redis作为其替代者，支持更为丰富的数据类型

<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> redis的速度比memcached快很多（其实差不多，分具体场景）

<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> redis可以持久化其数据</code></pre>
<h3 id="3-redis常见的性能问题和解决方案"><a href="#3-redis常见的性能问题和解决方案" class="headerlink" title="3 redis常见的性能问题和解决方案"></a>3 redis常见的性能问题和解决方案</h3><pre class=" language-python"><code class="language-python"><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> Master最好不要做任何持久化工作，如RDB内存快照和AOF日志文件

<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span> 如果数据比较重要，某个Slave开启AOF备份数据，策略设置为每秒同步一次

<span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span> 为了主从复制的速度和连接的稳定性，Master和Slave最好在同一个局域网内

<span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span> 尽量避免在压力很大的主库上增加从库

<span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span> 主从复制不要用图状结构，用单向链表结构更为稳定，即：Master <span class="token operator">&lt;</span><span class="token operator">-</span> Slave1 <span class="token operator">&lt;</span><span class="token operator">-</span> Slave2 <span class="token operator">&lt;</span><span class="token operator">-</span> Slave3<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>

这样的结构方便解决单点故障问题，实现Slave对Master的替换。如果Master挂了，可以立刻启用Slave1做Master，其他不变。</code></pre>
<h3 id="4-MySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据"><a href="#4-MySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据" class="headerlink" title="4 MySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据"></a>4 MySQL里有2000w数据，redis中只存20w的数据，如何保证redis中的数据都是热点数据</h3><pre class=" language-python"><code class="language-python"> 相关知识：redis 内存数据集大小上升到一定大小的时候，就会施行数据淘汰策略。redis 提供 <span class="token number">6</span>种数据淘汰策略：

voltile<span class="token operator">-</span>lru：从已设置过期时间的数据集（server<span class="token punctuation">.</span>db<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>expires）中挑选最近最少使用的数据淘汰

volatile<span class="token operator">-</span>ttl：从已设置过期时间的数据集（server<span class="token punctuation">.</span>db<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>expires）中挑选将要过期的数据淘汰

volatile<span class="token operator">-</span>random：从已设置过期时间的数据集（server<span class="token punctuation">.</span>db<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>expires）中任意选择数据淘汰

allkeys<span class="token operator">-</span>lru：从数据集（server<span class="token punctuation">.</span>db<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>dict）中挑选最近最少使用的数据淘汰

allkeys<span class="token operator">-</span>random：从数据集（server<span class="token punctuation">.</span>db<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>dict）中任意选择数据淘汰

no<span class="token operator">-</span>enviction（驱逐）：禁止驱逐数据</code></pre>
<h3 id="5-redis-最适合的场景"><a href="#5-redis-最适合的场景" class="headerlink" title="5 redis 最适合的场景"></a>5 redis 最适合的场景</h3><pre class=" language-python"><code class="language-python">Redis最适合所有数据<span class="token keyword">in</span><span class="token operator">-</span>momory的场景，虽然Redis也提供持久化功能，但实际更多的是一个disk<span class="token operator">-</span>backed的功能，跟传统意义上的持久化有比较大的差别，那么可能大家就会有疑问，似乎Redis更像一个加强版的Memcached，那么何时使用Memcached<span class="token punctuation">,</span>何时使用Redis呢?

       如果简单地比较Redis与Memcached的区别，大多数都会得到以下观点：

     <span class="token number">1</span> 、Redis不仅仅支持简单的k<span class="token operator">/</span>v类型的数据，同时还提供list，set，zset，hash等数据结构的存储。
     <span class="token number">2</span> 、Redis支持数据的备份，即master<span class="token operator">-</span>slave模式的数据备份。
     <span class="token number">3</span> 、Redis支持数据的持久化，可以将内存中的数据保持在磁盘中，重启的时候可以再次加载进行使用。

（<span class="token number">1</span>）、会话缓存（Session Cache）

最常用的一种使用Redis的情景是会话缓存（session cache）。用Redis缓存会话比其他存储（如Memcached）的优势在于：Redis提供持久化。当维护一个不是严格要求一致性的缓存时，如果用户的购物车信息全部丢失，大部分人都会不高兴的，现在，他们还会这样吗？

幸运的是，随着 Redis 这些年的改进，很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。

（<span class="token number">2</span>）、全页缓存（FPC）

除基本的会话token之外，Redis还提供很简便的FPC平台。回到一致性问题，即使重启了Redis实例，因为有磁盘的持久化，用户也不会看到页面加载速度的下降，这是一个极大改进，类似PHP本地FPC。

再次以Magento为例，Magento提供一个插件来使用Redis作为全页缓存后端。

此外，对WordPress的用户来说，Pantheon有一个非常好的插件  wp<span class="token operator">-</span>redis，这个插件能帮助你以最快速度加载你曾浏览过的页面。

（<span class="token number">3</span>）、队列

Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作，这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作，就类似于本地程序语言（如Python）对 list 的 push<span class="token operator">/</span>pop 操作。

如果你快速的在Google中搜索“Redis queues”，你马上就能找到大量的开源项目，这些项目的目的就是利用Redis创建非常好的后端工具，以满足各种队列需求。例如，Celery有一个后台就是使用Redis作为broker，你可以从这里去查看。

（<span class="token number">4</span>），排行榜<span class="token operator">/</span>计数器

Redis在内存中对数字进行递增或递减的操作实现的非常好。集合（Set）和有序集合（Sorted Set）也使得我们在执行这些操作的时候变的非常简单，Redis只是正好提供了这两种数据结构。所以，我们要从排序集合中获取到排名最靠前的<span class="token number">10</span>个用户–我们称之为“user_scores”，我们只需要像下面一样执行即可：

当然，这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数，你需要这样执行：

ZRANGE user_scores <span class="token number">0</span> <span class="token number">10</span> WITHSCORES

Agora Games就是一个很好的例子，用Ruby实现的，它的排行榜就是使用Redis来存储数据的，你可以在这里看到。

（<span class="token number">5</span>）、发布<span class="token operator">/</span>订阅

最后（但肯定不是最不重要的）是Redis的发布<span class="token operator">/</span>订阅功能。发布<span class="token operator">/</span>订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用，还可作为基于发布<span class="token operator">/</span>订阅的脚本触发器，甚至用Redis的发布<span class="token operator">/</span>订阅功能来建立聊天系统！（不，这是真的，你可以去核实）。

Redis提供的所有特性中，我感觉这个是喜欢的人最少的一个，虽然它为用户提供如果此多功能。</code></pre>
<h2 id="二、基本使用"><a href="#二、基本使用" class="headerlink" title="二、基本使用"></a>二、基本使用</h2><p>安装好redis后，顺便可以安装一个Another Redis Desktop Manager，这是redis版的navicat</p>
<ul>
<li><code>redis-server</code>启动服务端（通常会自动设成自启服务，不需要手动开）</li>
<li><code>redis-cli</code>启动客户端</li>
<li>python中安装操作redis的模块  <code>pip install redis</code></li>
</ul>
<h3 id="1-python操作redis之普通链接"><a href="#1-python操作redis之普通链接" class="headerlink" title="1 python操作redis之普通链接"></a>1 python操作redis之普通链接</h3><pre class=" language-python"><code class="language-python"><span class="token keyword">import</span> redis
<span class="token comment" spellcheck="true"># Redis实例化有很多可以设定的参数，其中decode_responses=True是把拿到的二进制数据转换成字符串</span>
conn <span class="token operator">=</span> redis<span class="token punctuation">.</span>Redis<span class="token punctuation">(</span>decode_responses<span class="token operator">=</span><span class="token boolean">True</span><span class="token punctuation">)</span>
conn<span class="token punctuation">.</span>set<span class="token punctuation">(</span><span class="token string">'name'</span><span class="token punctuation">,</span><span class="token string">'hz'</span><span class="token punctuation">)</span>
res <span class="token operator">=</span> conn<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'name'</span><span class="token punctuation">)</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span></code></pre>
<h3 id="2-python操作redis之连接池"><a href="#2-python操作redis之连接池" class="headerlink" title="2 python操作redis之连接池"></a>2 python操作redis之连接池</h3><pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># 用连接池来管理链接对象，如果每一次请求都要建立链接，当请求量很大时会造成内存堵塞</span>
<span class="token comment" spellcheck="true"># 连接池的连接数量是固定的，超过这个最大链接数的其他链接只能在外面等着</span>
<span class="token comment" spellcheck="true"># 这里注意连接池要做成单例模式，不然每次链接进来都要实例化一个连接池，那限定的意义就没了</span>
<span class="token keyword">import</span> redis
pool <span class="token operator">=</span> redis<span class="token punctuation">.</span>ConnectionPool<span class="token punctuation">(</span>host<span class="token operator">=</span><span class="token string">'127.0.0.1'</span><span class="token punctuation">,</span> port<span class="token operator">=</span><span class="token number">6379</span><span class="token punctuation">)</span>
r <span class="token operator">=</span> redis<span class="token punctuation">.</span>Redis<span class="token punctuation">(</span>connection_pool<span class="token operator">=</span>pool<span class="token punctuation">)</span>
r<span class="token punctuation">.</span>set<span class="token punctuation">(</span><span class="token string">'foo'</span><span class="token punctuation">,</span> <span class="token string">'Bar'</span><span class="token punctuation">)</span>
<span class="token keyword">print</span><span class="token punctuation">(</span>r<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'foo'</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h2 id="三、redis字符串操作"><a href="#三、redis字符串操作" class="headerlink" title="三、redis字符串操作"></a>三、redis字符串操作</h2><p><strong>set(name, value, ex=None, px=None, nx=False, xx=False)</strong></p>
<pre><code>在Redis中设置值，默认，不存在则创建，存在则修改
参数：
     ex，过期时间（秒）
     px，过期时间（毫秒）
     nx，如果设置为True，则只有name不存在时，当前set操作才执行,值存在，就修改不了，执行没效果
     xx，如果设置为True，则只有name存在时，当前set操作才执行，值存在才能修改，值不存在，不会设置新值</code></pre>
<p><strong>setnx(name, value)</strong></p>
<pre><code>设置值，只有name不存在时，执行设置操作（添加）,如果存在，不会修改</code></pre>
<p><strong>setex(name, value, time)</strong></p>
<pre><code># 设置值
# 参数：
    # time，过期时间（数字秒 或 timedelta对象）</code></pre>
<p><strong>psetex(name, time_ms, value)</strong></p>
<pre><code># 设置值
# 参数：
    # time_ms，过期时间（数字毫秒 或 timedelta对象</code></pre>
<p><strong>mset(*args, \</strong>kwargs)**</p>
<pre><code>批量设置值
如：
    mset(k1=&#39;v1&#39;, k2=&#39;v2&#39;)
    或
    mget(&#123;&#39;k1&#39;: &#39;v1&#39;, &#39;k2&#39;: &#39;v2&#39;&#125;)</code></pre>
<p><strong>get(name)</strong></p>
<pre><code>获取值</code></pre>
<p><strong>mget(keys, *args)</strong></p>
<pre><code>批量获取
如：
    mget(&#39;k1&#39;, &#39;k2&#39;)
    或
    r.mget([&#39;k3&#39;, &#39;k4&#39;])</code></pre>
<p><strong>getset(name, value)</strong></p>
<pre><code>设置新值并获取原来的值</code></pre>
<p><strong>getrange(key, start, end)</strong></p>
<pre><code># 获取子序列（根据字节获取，非字符）
# 参数：
    # name，Redis 的 name
    # start，起始位置（字节）
    # end，结束位置（字节）
# 如： &quot;刘清政&quot; ，0-3表示 &quot;刘&quot;</code></pre>
<p><strong>setrange(name, offset, value)</strong></p>
<pre><code># 修改字符串内容，从指定字符串索引开始向后替换（新值太长时，则向后添加）
# 参数：
    # offset，字符串的索引，字节（一个汉字三个字节）
    # value，要设置的值</code></pre>
<p><strong>setbit(name, offset, value)</strong></p>
<pre><code># 对name对应值的二进制表示的位进行操作

# 参数：
    # name，redis的name
    # offset，位的索引（将值变换成二进制后再进行索引）
    # value，值只能是 1 或 0

# 注：如果在Redis中有一个对应： n1 = &quot;foo&quot;，
        那么字符串foo的二进制表示为：01100110 01101111 01101111
    所以，如果执行 setbit(&#39;n1&#39;, 7, 1)，则就会将第7位设置为1，
        那么最终二进制则变成 01100111 01101111 01101111，即：&quot;goo&quot;</code></pre>
<p><strong>getbit(name, offset)</strong></p>
<pre><code># 获取name对应的值的二进制表示中的某位的值 （0或1）</code></pre>
<p><strong>bitcount(key, start=None, end=None)</strong></p>
<pre><code># 获取name对应的值的二进制表示中 1 的个数
# 参数：
    # key，Redis的name
    # start，位起始位置
    # end，位结束位置</code></pre>
<p><strong>bitop(operation, dest, *keys)</strong></p>
<pre><code># 获取多个值，并将值做位运算，将最后的结果保存至新的name对应的值

# 参数：
    # operation,AND（并） 、 OR（或） 、 NOT（非） 、 XOR（异或）
    # dest, 新的Redis的name
    # *keys,要查找的Redis的name

# 如：
    bitop(&quot;AND&quot;, &#39;new_name&#39;, &#39;n1&#39;, &#39;n2&#39;, &#39;n3&#39;)
    # 获取Redis中n1,n2,n3对应的值，然后讲所有的值做位运算（求并集），然后将结果保存 new_name 对应的值中</code></pre>
<p><strong>strlen(name)</strong></p>
<pre><code># 返回name对应值的字节长度（一个汉字3个字节）</code></pre>
<p><strong>incr(self, name, amount=1)</strong></p>
<pre><code># 自增 name对应的值，当name不存在时，则创建name＝amount，否则，则自增。

# 参数：
    # name,Redis的name
    # amount,自增数（必须是整数）

# 注：同incrby</code></pre>
<p><strong>incrbyfloat(self, name, amount=1.0)</strong></p>
<pre><code># 自增 name对应的值，当name不存在时，则创建name＝amount，否则，则自增。

# 参数：
    # name,Redis的name
    # amount,自增数（浮点型）</code></pre>
<p><strong>decr(self, name, amount=1)</strong></p>
<pre><code># 自减 name对应的值，当name不存在时，则创建name＝amount，否则，则自减。

# 参数：
    # name,Redis的name
    # amount,自减数（整数）</code></pre>
<p><strong>append(key, value)</strong></p>
<pre><code># 在redis name对应的值后面追加内容

# 参数：
    key, redis的name
    value, 要追加的字符串</code></pre>
<p><strong>总结</strong>：</p>
<p>需要注意的操作：</p>
<ul>
<li>set  存值，有很多可以修改的参数，主要是可以设置超时时间</li>
<li>get  获取值，没有返回None</li>
<li>mset 批量存值，可以传一个字典，也可直接传关键字参数</li>
<li>mget 批量取值</li>
<li>incr name存在就自增，没有就新增，并设置自增最小值</li>
<li>decr 自减，本质上和上面一样，甚至incr设置为负数也能完成一样的操作</li>
<li>append 对指定的key的value拼接字符串</li>
</ul>
<h2 id="四、redis哈希类型操作"><a href="#四、redis哈希类型操作" class="headerlink" title="四、redis哈希类型操作"></a>四、redis哈希类型操作</h2><p><strong>hset(name, key, value)</strong></p>
<pre><code># name对应的hash中设置一个键值对（不存在，则创建；否则，修改）

# 参数：
    # name，redis的name
    # key，name对应的hash中的key
    # value，name对应的hash中的value

# 注：
    # hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建（相当于添加）</code></pre>
<p><strong>hmset(name, mapping)</strong></p>
<pre><code># 在name对应的hash中批量设置键值对

# 参数：
    # name，redis的name
    # mapping，字典，如：&#123;&#39;k1&#39;:&#39;v1&#39;, &#39;k2&#39;: &#39;v2&#39;&#125;

# 如：
    # r.hmset(&#39;xx&#39;, &#123;&#39;k1&#39;:&#39;v1&#39;, &#39;k2&#39;: &#39;v2&#39;&#125;)</code></pre>
<p><strong>hget(name,key)</strong></p>
<pre><code># 在name对应的hash中获取根据key获取value</code></pre>
<p><strong>hmget(name, keys, *args)</strong></p>
<pre><code># 在name对应的hash中获取多个key的值

# 参数：
    # name，reids对应的name
    # keys，要获取key集合，如：[&#39;k1&#39;, &#39;k2&#39;, &#39;k3&#39;]
    # *args，要获取的key，如：k1,k2,k3

# 如：
    # r.mget(&#39;xx&#39;, [&#39;k1&#39;, &#39;k2&#39;])
    # 或
    # print r.hmget(&#39;xx&#39;, &#39;k1&#39;, &#39;k2&#39;)</code></pre>
<p><strong>hgetall(name)</strong></p>
<pre><code># 获取name对应hash的所有键值
print(re.hgetall(&#39;xxx&#39;).get(b&#39;name&#39;))</code></pre>
<p><strong>hlen(name)</strong></p>
<pre><code># 获取name对应的hash中键值对的个数</code></pre>
<p><strong>hkeys(name)</strong></p>
<pre><code># 获取name对应的hash中所有的key的值</code></pre>
<p><strong>hvals(name)</strong></p>
<pre><code># 获取name对应的hash中所有的value的值</code></pre>
<p><strong>hexists(name, key)</strong></p>
<pre><code># 检查name对应的hash是否存在当前传入的key</code></pre>
<p><strong>hdel(name,*keys)</strong></p>
<pre><code># 将name对应的hash中指定key的键值对删除
print(re.hdel(&#39;xxx&#39;,&#39;sex&#39;,&#39;name&#39;))</code></pre>
<p><strong>hincrby(name, key, amount=1)</strong></p>
<pre><code># 自增name对应的hash中的指定key的值，不存在则创建key=amount
# 参数：
    # name，redis中的name
    # key， hash对应的key
    # amount，自增数（整数）</code></pre>
<p><strong>hincrbyfloat(name, key, amount=1.0)</strong></p>
<pre><code># 自增name对应的hash中的指定key的值，不存在则创建key=amount

# 参数：
    # name，redis中的name
    # key， hash对应的key
    # amount，自增数（浮点数）

# 自增name对应的hash中的指定key的值，不存在则创建key=amount</code></pre>
<p><strong>hscan(name, cursor=0, match=None, count=None)</strong></p>
<pre><code># 增量式迭代获取，对于数据大的数据非常有用，hscan可以实现分片的获取数据，并非一次性将数据全部获取完，从而放置内存被撑爆

# 参数：
    # name，redis的name
    # cursor，游标（基于游标分批取获取数据）
    # match，匹配指定key，默认None 表示所有的key
    # count，每次分片最少获取个数，默认None表示采用Redis的默认分片个数

# 如：
    # 第一次：cursor1, data1 = r.hscan(&#39;xx&#39;, cursor=0, match=None, count=None)
    # 第二次：cursor2, data1 = r.hscan(&#39;xx&#39;, cursor=cursor1, match=None, count=None)
    # ...
    # 直到返回值cursor的值为0时，表示数据已经通过分片获取完毕</code></pre>
<p><strong>hscan_iter(name, match=None, count=None)</strong></p>
<pre><code># 利用yield封装hscan创建生成器，实现分批去redis中获取数据

# 参数：
    # match，匹配指定key，默认None 表示所有的key
    # count，每次分片最少获取个数，默认None表示采用Redis的默认分片个数

# 如：
    # for item in r.hscan_iter(&#39;xx&#39;):
    #     print item</code></pre>
<p><strong>总结：</strong></p>
<p>需要注意的操作：</p>
<ul>
<li>hset 给name的value设置{key,value}的值，存在就修改</li>
<li>hget 获取值</li>
<li>hmset 批量设置，mapping参数放一个字典</li>
<li>hmget 批量获取</li>
<li>hincrby 自增name对应的key值，不存在则创建key：amout（自增数），只能自增value是数字的类型</li>
<li>hgetall 获取name对于的hash的所有键值</li>
<li>hscan_iter  利用yield创建生成器，分批去redis中取值</li>
</ul>
<h2 id="五、redis链表类型操作"><a href="#五、redis链表类型操作" class="headerlink" title="五、redis链表类型操作"></a>五、redis链表类型操作</h2><p><strong>lpush(name,values)</strong></p>
<pre><code># 在name对应的list中添加元素，每个新的元素都添加到列表的最左边

# 如：
    # r.lpush(&#39;oo&#39;, 11,22,33)
    # 保存顺序为: 33,22,11

# 扩展：
    # rpush(name, values) 表示从右向左操作</code></pre>
<p><strong>lpushx(name,value)</strong></p>
<pre><code># 在name对应的list中添加元素，只有name已经存在时，值添加到列表的最左边

# 更多：
    # rpushx(name, value) 表示从右向左操作</code></pre>
<p><strong>llen(name)</strong></p>
<pre><code># name对应的list元素的个数</code></pre>
<p><strong>linsert(name, where, refvalue, value))</strong></p>
<pre><code># 在name对应的列表的某一个值前或后插入一个新值

# 参数：
    # name，redis的name
    # where，BEFORE或AFTER(小写也可以)
    # refvalue，标杆值，即：在它前后插入数据（如果存在多个标杆值，以找到的第一个为准）
    # value，要插入的数据</code></pre>
<p><strong>r.lset(name, index, value)</strong></p>
<pre><code># 对name对应的list中的某一个索引位置重新赋值

# 参数：
    # name，redis的name
    # index，list的索引位置
    # value，要设置的值</code></pre>
<p><strong>r.lrem(name, value, num)</strong></p>
<pre><code># 在name对应的list中删除指定的值

# 参数：
    # name，redis的name
    # value，要删除的值
    # num，  num=0，删除列表中所有的指定值；
           # num=2,从前到后，删除2个；
           # num=-2,从后向前，删除2个</code></pre>
<p><strong>lpop(name)</strong></p>
<pre><code># 在name对应的列表的左侧获取第一个元素并在列表中移除，返回值则是第一个元素

# 更多：
    # rpop(name) 表示从右向左操作</code></pre>
<p><strong>lindex(name, index)</strong></p>
<pre><code>在name对应的列表中根据索引获取列表元素</code></pre>
<p><strong>lrange(name, start, end)</strong></p>
<pre><code># 在name对应的列表分片获取数据
# 参数：
    # name，redis的name
    # start，索引的起始位置
    # end，索引结束位置  print(re.lrange(&#39;aa&#39;,0,re.llen(&#39;aa&#39;)))</code></pre>
<p><strong>ltrim(name, start, end)</strong></p>
<pre><code># 在name对应的列表中移除没有在start-end索引之间的值
# 参数：
    # name，redis的name
    # start，索引的起始位置
    # end，索引结束位置（大于列表长度，则代表不移除任何）</code></pre>
<p><strong>rpoplpush(src, dst)</strong></p>
<pre><code># 从一个列表取出最右边的元素，同时将其添加至另一个列表的最左边
# 参数：
    # src，要取数据的列表的name
    # dst，要添加数据的列表的name</code></pre>
<p><strong>blpop(keys, timeout)</strong></p>
<pre><code># 将多个列表排列，按照从左到右去pop对应列表的元素

# 参数：
    # keys，redis的name的集合
    # timeout，超时时间，当元素所有列表的元素获取完之后，阻塞等待列表内有数据的时间（秒）, 0 表示永远阻塞

# 更多：
    # r.brpop(keys, timeout)，从右向左获取数据爬虫实现简单分布式：多个url放到列表里，往里不停放URL，程序循环取值，但是只能一台机器运行取值，可以把url放到redis中，多台机器从redis中取值，爬取数据，实现简单分布式</code></pre>
<p><strong>brpoplpush(src, dst, timeout=0)</strong></p>
<pre><code># 从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧

# 参数：
    # src，取出并要移除元素的列表对应的name
    # dst，要插入元素的列表对应的name
    # timeout，当src对应的列表中没有数据时，阻塞等待其有数据的超时时间（秒），0 表示永远阻塞</code></pre>
<p><strong>自定义增量迭代</strong></p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># 由于redis类库中没有提供对列表元素的增量迭代，如果想要循环name对应的列表的所有元素，那么就需要：</span>
    <span class="token comment" spellcheck="true"># 1、获取name对应的所有列表</span>
    <span class="token comment" spellcheck="true"># 2、循环列表</span>
<span class="token comment" spellcheck="true"># 但是，如果列表非常大，那么就有可能在第一步时就将程序的内容撑爆，所有有必要自定义一个增量迭代的功能：</span>
<span class="token keyword">import</span> redis
conn<span class="token operator">=</span>redis<span class="token punctuation">.</span>Redis<span class="token punctuation">(</span>host<span class="token operator">=</span><span class="token string">'127.0.0.1'</span><span class="token punctuation">,</span>port<span class="token operator">=</span><span class="token number">6379</span><span class="token punctuation">)</span>
<span class="token comment" spellcheck="true"># conn.lpush('test',*[1,2,3,4,45,5,6,7,7,8,43,5,6,768,89,9,65,4,23,54,6757,8,68])</span>
<span class="token comment" spellcheck="true"># conn.flushall()</span>
<span class="token keyword">def</span> <span class="token function">scan_list</span><span class="token punctuation">(</span>name<span class="token punctuation">,</span>count<span class="token operator">=</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    index<span class="token operator">=</span><span class="token number">0</span>
    <span class="token keyword">while</span> <span class="token boolean">True</span><span class="token punctuation">:</span>
        data_list<span class="token operator">=</span>conn<span class="token punctuation">.</span>lrange<span class="token punctuation">(</span>name<span class="token punctuation">,</span>index<span class="token punctuation">,</span>count<span class="token operator">+</span>index<span class="token number">-1</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span> <span class="token operator">not</span> data_list<span class="token punctuation">:</span>
            <span class="token keyword">return</span>
        index<span class="token operator">+=</span>count
        <span class="token keyword">for</span> item <span class="token keyword">in</span> data_list<span class="token punctuation">:</span>
            <span class="token keyword">yield</span> item
<span class="token keyword">print</span><span class="token punctuation">(</span>conn<span class="token punctuation">.</span>lrange<span class="token punctuation">(</span><span class="token string">'test'</span><span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">,</span><span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token keyword">for</span> item <span class="token keyword">in</span> scan_list<span class="token punctuation">(</span><span class="token string">'test'</span><span class="token punctuation">,</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'---'</span><span class="token punctuation">)</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span></code></pre>
<p><strong>总结</strong>：</p>
<p>需要注意的操作：</p>
<ul>
<li>lpush 每个新元素都添加到列表的最左边，最早来的在最后，rpush与之相反</li>
<li>lpop 删除name对应列表的左侧的第一个值，并返回，rpop与之相反</li>
<li>blpop 将多个列表排列从左到右pop对于列表的元素阻塞时间内如果还有新增数据，就会继续pop</li>
<li>lrange 切片start开始，end结束，闭区间</li>
<li>llen 统计元素个数</li>
</ul>
<h2 id="六、其他操作"><a href="#六、其他操作" class="headerlink" title="六、其他操作"></a>六、其他操作</h2><p><strong>delete(*names)</strong></p>
<pre><code># 根据删除redis中的任意数据类型</code></pre>
<p><strong>exists(name)</strong></p>
<pre><code># 检测redis的name是否存在</code></pre>
<p><strong>keys(pattern=’*‘)</strong></p>
<pre><code># 根据模型获取redis的name（其实就是通过正则匹配）

# 更多：
    # KEYS * 匹配数据库中所有 key 。
    # KEYS h?llo 匹配 hello ， hallo 和 hxllo 等。
    # KEYS h*llo 匹配 hllo 和 heeeeello 等。
    # KEYS h[ae]llo 匹配 hello 和 hallo ，但不匹配 hillo </code></pre>
<p><strong>expire(name ,time)</strong></p>
<pre><code># 为某个redis的某个name设置超时时间</code></pre>
<p><strong>rename(src, dst)</strong></p>
<pre><code># 对redis的name重命名为</code></pre>
<p><strong>move(name, db))</strong></p>
<pre><code># 将redis的某个值移动到指定的db下（换数据库）</code></pre>
<p><strong>randomkey()</strong></p>
<pre><code># 随机获取一个redis的name（不删除）（抽奖）</code></pre>
<p><strong>type(name)</strong></p>
<pre><code># 获取name对应值的类型</code></pre>
<p><strong>scan(cursor=0, match=None, count=None)</strong><br><strong>scan_iter(match=None, count=None)</strong></p>
<pre><code># 同字符串操作，用于增量迭代获取key</code></pre>
<h2 id="七、管道"><a href="#七、管道" class="headerlink" title="七、管道"></a>七、管道</h2><pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># redis支持事务</span>
<span class="token comment" spellcheck="true"># 管道实现事务</span>
<span class="token comment" spellcheck="true"># import redis</span>
<span class="token comment" spellcheck="true"># pool = redis.ConnectionPool(host='127.0.0.1', port=6379)</span>
<span class="token comment" spellcheck="true"># </span>
<span class="token comment" spellcheck="true"># conn = redis.Redis(connection_pool=pool)</span>
<span class="token comment" spellcheck="true"># </span>
<span class="token comment" spellcheck="true"># # pipe = r.pipeline(transaction=False)</span>
<span class="token comment" spellcheck="true"># pipe = conn.pipeline(transaction=True)</span>
<span class="token comment" spellcheck="true"># pipe.multi() # 开启管道，开启事务</span>
<span class="token comment" spellcheck="true"># pipe.set('name', 'alex')</span>
<span class="token comment" spellcheck="true"># </span>
<span class="token comment" spellcheck="true"># pipe.set('role', 'sb')</span>
<span class="token comment" spellcheck="true"># </span>
<span class="token comment" spellcheck="true"># pipe.execute()  # 这句话，才真正的去执行，结束管道</span></code></pre>
<h2 id="八、django中使用redis"><a href="#八、django中使用redis" class="headerlink" title="八、django中使用redis"></a>八、django中使用redis</h2><pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># 方式一（通用方式）</span>
<span class="token comment" spellcheck="true"># 方式二：django-redis</span>
    <span class="token operator">-</span>pip install django<span class="token operator">-</span>redis
    <span class="token operator">-</span>setting中配置
        CACHES <span class="token operator">=</span> <span class="token punctuation">{</span>
                <span class="token string">"default"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                    <span class="token string">"BACKEND"</span><span class="token punctuation">:</span> <span class="token string">"django_redis.cache.RedisCache"</span><span class="token punctuation">,</span>
                    <span class="token string">"LOCATION"</span><span class="token punctuation">:</span> <span class="token string">"redis://127.0.0.1:6379"</span><span class="token punctuation">,</span>
                    <span class="token string">"OPTIONS"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                        <span class="token string">"CLIENT_CLASS"</span><span class="token punctuation">:</span> <span class="token string">"django_redis.client.DefaultClient"</span><span class="token punctuation">,</span>
                        <span class="token string">"CONNECTION_POOL_KWARGS"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span><span class="token string">"max_connections"</span><span class="token punctuation">:</span> <span class="token number">100</span><span class="token punctuation">}</span>
                        <span class="token comment" spellcheck="true"># "PASSWORD": "123",</span>
                    <span class="token punctuation">}</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
       <span class="token operator">-</span>使用两种方式
        <span class="token number">1</span> 使用cache
        <span class="token keyword">from</span> django<span class="token punctuation">.</span>core<span class="token punctuation">.</span>cache <span class="token keyword">import</span> cache
        cache<span class="token punctuation">.</span>set<span class="token punctuation">(</span><span class="token string">'name'</span><span class="token punctuation">,</span>user<span class="token punctuation">)</span> 
        <span class="token number">2</span> 直接使用conn对象
        <span class="token keyword">from</span> django_redis <span class="token keyword">import</span> get_redis_connection
        conn <span class="token operator">=</span> get_redis_connection<span class="token punctuation">(</span><span class="token string">'default'</span><span class="token punctuation">)</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span>conn<span class="token punctuation">.</span>hgetall<span class="token punctuation">(</span><span class="token string">'xxx'</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<h2 id="九、接口缓存"><a href="#九、接口缓存" class="headerlink" title="九、接口缓存"></a>九、接口缓存</h2><p>接口缓存简单来说就是把需要经常从mysql数据查的数据放到redis等内存数据库（快速读取）</p>
<pre class=" language-python"><code class="language-python"><span class="token comment" spellcheck="true"># 首页轮播图数据缓存到redis中</span>
<span class="token keyword">def</span> <span class="token function">list</span><span class="token punctuation">(</span>self<span class="token punctuation">,</span> request<span class="token punctuation">,</span> <span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span><span class="token punctuation">:</span>

    <span class="token comment" spellcheck="true"># response=super().list(request, *args, **kwargs)</span>
    <span class="token comment" spellcheck="true"># 把data的数据加缓存</span>
    <span class="token comment" spellcheck="true"># 1 先去缓存拿数据</span>
    banner_list<span class="token operator">=</span>cache<span class="token punctuation">.</span>get<span class="token punctuation">(</span><span class="token string">'banner_list'</span><span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token operator">not</span> banner_list<span class="token punctuation">:</span>
        <span class="token keyword">print</span><span class="token punctuation">(</span><span class="token string">'走数据库了'</span><span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 缓存中没有，去数据库拿</span>
        response <span class="token operator">=</span> super<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>list<span class="token punctuation">(</span>request<span class="token punctuation">,</span> <span class="token operator">*</span>args<span class="token punctuation">,</span> <span class="token operator">**</span>kwargs<span class="token punctuation">)</span>
        <span class="token comment" spellcheck="true"># 加到缓存</span>
        cache<span class="token punctuation">.</span>set<span class="token punctuation">(</span><span class="token string">'banner_list'</span><span class="token punctuation">,</span>response<span class="token punctuation">.</span>data<span class="token punctuation">,</span><span class="token number">60</span><span class="token operator">*</span><span class="token number">60</span><span class="token operator">*</span><span class="token number">24</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> response

    <span class="token keyword">return</span> Response<span class="token punctuation">(</span>data<span class="token operator">=</span>banner_list<span class="token punctuation">)</span></code></pre>
</div><div id="reward-container"><span class="hty-icon-button button-glow" id="reward-button" title="打赏" onclick="var qr = document.getElementById(&quot;qr&quot;); qr.style.display = (qr.style.display === &quot;none&quot;) ? &quot;block&quot; : &quot;none&quot;;"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-hand-coin-line"></use></svg></span><div id="reward-comment">点我就给你看点有意思的</div><div id="qr" style="display:none;"><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/alipay.png"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/alipay.png" alt="支付宝" title="支付宝"></a><div><span style="color:#00A3EE"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-alipay-line"></use></svg></span></div></div><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/qqpay.jpg"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/qqpay.jpg" alt="QQ 支付" title="QQ 支付"></a><div><span style="color:#12B7F5"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-qq-line"></use></svg></span></div></div><div style="display:inline-block"><a target="_blank" rel="noopener" href="https://gitee.com/huang_zhao/hz/raw/master/hz/wxpay.jpg"><img loading="lazy" src="https://gitee.com/huang_zhao/hz/raw/master/hz/wxpay.jpg" alt="微信支付" title="微信支付"></a><div><span style="color:#2DC100"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-wechat-pay-line"></use></svg></span></div></div></div></div><ul class="post-copyright"><li class="post-copyright-author"><strong>本文作者：</strong>爱肖彤真是太好了</li><li class="post-copyright-link"><strong>本文链接：</strong><a href="http://huang_zhao.gitee.io/task/2021/06/27/%E6%95%B0%E6%8D%AE%E5%BA%93/redis/Redis/" title="Redis">http://huang_zhao.gitee.io/task/2021/06/27/%E6%95%B0%E6%8D%AE%E5%BA%93/redis/Redis/</a></li><li class="post-copyright-license"><strong>版权声明：</strong>本博客所有文章除特别声明外，均默认采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank" rel="noopener" title="CC BY-NC-SA 4.0 "><svg class="icon"><use xlink:href="#icon-creative-commons-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-by-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-nc-line"></use></svg><svg class="icon"><use xlink:href="#icon-creative-commons-sa-line"></use></svg></a> 许可协议。</li></ul></section></article><div class="post-nav"><div class="post-nav-item"><a class="post-nav-prev" href="/task/2021/06/27/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/%E6%B5%81%E7%95%85%E7%9A%84python%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/" rel="prev" title="流畅的python学习记录"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-left-s-line"></use></svg><span class="post-nav-text">流畅的python学习记录</span></a></div><div class="post-nav-item"><a class="post-nav-next" href="/task/2021/05/15/python/%E6%A1%86%E6%9E%B6/django%20%E7%9F%A5%E8%AF%86%E7%82%B9%E6%89%A9%E5%B1%95/" rel="next" title="django知识点扩展"><span class="post-nav-text">django知识点扩展</span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-right-s-line"></use></svg></a></div></div></div></main><footer class="sidebar-translate" id="footer"><div class="copyright"><span>&copy; 2019 – 2022 </span><span class="with-love" id="animate"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-cloud-line"></use></svg></span><span class="author"> 爱肖彤真是太好了</span></div><div class="powered"><span>由 <a href="https://hexo.io" target="_blank" rel="noopener">Hexo</a> 驱动 v5.1.1</span><span class="footer-separator">|</span><span>主题 - <a rel="noopener" href="https://github.com/YunYouJun/hexo-theme-yun" target="_blank"><span>Yun</span></a> v0.9.7</span></div><div class="live_time"><span>本博客已萌萌哒地运行</span><span id="display_live_time"></span><span class="moe-text">(●'◡'●)</span><script>function blog_live_time() {
  window.setTimeout(blog_live_time, 1000);
  const start = new Date('2019-04-12T00:00:00');
  const now = new Date();
  const timeDiff = (now.getTime() - start.getTime());
  const msPerMinute = 60 * 1000;
  const msPerHour = 60 * msPerMinute;
  const msPerDay = 24 * msPerHour;
  const passDay = Math.floor(timeDiff / msPerDay);
  const passHour = Math.floor((timeDiff % msPerDay) / 60 / 60 / 1000);
  const passMinute = Math.floor((timeDiff % msPerHour) / 60 / 1000);
  const passSecond = Math.floor((timeDiff % msPerMinute) / 1000);
  display_live_time.innerHTML = " " + passDay + " 天 " + passHour + " 小时 " + passMinute + " 分 " + passSecond + " 秒";
}
blog_live_time();
</script></div><div id="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_site_uv" title="总访客量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-user-line"></use></svg></span><span id="busuanzi_value_site_uv"></span></span><span class="footer-separator">|</span><span id="busuanzi_container_site_pv" title="总访问量"><span><svg class="icon" aria-hidden="true"><use xlink:href="#icon-eye-line"></use></svg></span><span id="busuanzi_value_site_pv"></span></span></div></footer><a class="hty-icon-button" id="goUp" aria-label="back-to-top" href="#"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-arrow-up-s-line"></use></svg><svg class="progress-circle-container" viewBox="0 0 100 100"><circle class="progress-circle" id="progressCircle" cx="50" cy="50" r="48" fill="none" stroke="#0078E7" stroke-width="2" stroke-linecap="round"></circle></svg></a><a class="popup-trigger hty-icon-button icon-search" id="search" href="javascript:;" title="搜索"><span class="site-state-item-icon"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-search-line"></use></svg></span></a><script>window.addEventListener("DOMContentLoaded", () => {
  // Handle and trigger popup window
  document.querySelector(".popup-trigger").addEventListener("click", () => {
    document.querySelector(".popup").classList.add("show");
    setTimeout(() => {
      document.querySelector(".search-input").focus();
    }, 100);
  });

  // Monitor main search box
  const onPopupClose = () => {
    document.querySelector(".popup").classList.remove("show");
  };

  document.querySelector(".popup-btn-close").addEventListener("click", () => {
    onPopupClose();
  });

  window.addEventListener("keyup", event => {
    if (event.key === "Escape") {
      onPopupClose();
    }
  });
});
</script><script src="/task/js/search/local-search.js" defer></script><div class="popup search-popup"><div class="search-header"><span class="popup-btn-close close-icon hty-icon-button"><svg class="icon" aria-hidden="true"><use xlink:href="#icon-close-line"></use></svg></span></div><div class="search-input-container"><input class="search-input" id="local-search-input" type="text" placeholder="搜索..." value=""></div><div id="local-search-result"></div></div></div><script defer src="/task/js/utils.js"></script><script defer src="/task/js/hexo-theme-yun.js"></script></body></html>